import java.rmi.Remote;
import java.rmi.RemoteException;


public interface iNode extends Remote {
	
	/**
	 * @return next node in the ring
	 */
	iNode getNext() throws RemoteException;
	
	/**
	 * @return previous node in the ring
	 */
	iNode getPrev() throws RemoteException;
	
	/**
	 * @return text identifier of this node (IP address)
	 */
	String getID() throws RemoteException;
	
	/**
	 * Recursively (?) looks up which Node is responsible for Key k
	 * @param the key (hashed) which is being requested
	 * @return Node that has key K in the ring
	 */
	iNode lookup(String k) throws RemoteException;
	
	/**
	 * Request to join an existing Ring
	 */
	void join(String bootIP) throws RemoteException;
	
	/**
	 * Add the specified Node into the Ring
	 * @param node The node to be added
	 */
	void addNodeToRing(iNode node) throws RemoteException;
	
	void setNext(iNode node) throws RemoteException;
	void setPrev(iNode node) throws RemoteException;
	
	/**
	 * Leave the ring. Removes itself correctly from the ring anad transfers data items
	 * to a new proper owner.
	 */
	void leave() throws RemoteException;
	
	/**
	 * Return the requested data item based on the Key k (hashed).
	 * Note that this data must be stored at this node - lookup is a separate
	 * method and not run as part of this.
	 * @param k Hashed key corresponding to the value/data that requestor needs
	 * @return The value/data corresponding to the Key k
	 */
	Object get(String k) throws RemoteException;
	
	/**
	 * Store value/data matching the given Key k
	 * Note that this data is meant to be stored at this node - lookup is a separate
	 * method and not run as part of this.
	 * @param k hashed Key corresponding to the given data
	 * @param data The data to be stored at this node according to key K
	 */
	void put(String k, Object data) throws RemoteException;
	
	/*
	 * Unimplemented methods that might be needed later:
	 * void changeNext(Node next); <- assigning a new successor but does not update prev of old/new successor
	 * void changePrev(Node prev); <- assigning a new predecessor but does not update next of old/new predecessor
	 * Map<Integer, Object> getAll(int k1, int k2); <- get all data items from excl k1 to incl k2 like when joining a ring
	 * void putAll(Map<Integer, Object> values); <- for storing all data items, like when leaving a ring
	 */
}
